/**
 * @file user_mqtt.c
 * @brief MQTT客户端实现
 * 
 * 实现MQTT连接、订阅、消息发布和回调处理。
 */

#include "user_mqtt.h"
#include "user_config.h"
#include "log_utils.h"
#include "esp_log.h"
#include "mqtt_client.h"
#include "user_gpio.h"

static const char *TAG = "user_mqtt";

// MQTT客户端句柄
static esp_mqtt_client_handle_t client = NULL;
static bool mqtt_connected = false;

// 函数声明
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);

/**
 * @brief 初始化MQTT客户端
 * 
 * 创建并配置MQTT客户端，启动连接过程。
 */
void user_mqtt_init(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = CONFIG_MQTT_BROKER_URI,
    };
    
    client = esp_mqtt_client_init(&mqtt_cfg);
    if (client == NULL) {
        ESP_LOGE(TAG, "MQTT客户端初始化失败");
        return;
    }
    
    // 注册事件处理函数
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    
    // 启动MQTT客户端
    esp_mqtt_client_start(client);
    ESP_LOGI(TAG, "MQTT客户端已启动，连接到: %s", CONFIG_MQTT_BROKER_URI);
}

/**
 * @brief MQTT事件处理函数
 * 
 * 处理MQTT连接、断开、消息接收等事件。
 */
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    esp_mqtt_event_handle_t event = event_data;
    
    switch ((esp_mqtt_event_id_t)event_id) {
        case MQTT_EVENT_CONNECTED:
            ESP_LOGI(TAG, "MQTT已连接");
            mqtt_connected = true;
            
            // 订阅LED控制主题
            int msg_id = esp_mqtt_client_subscribe(client, CONFIG_MQTT_TOPIC_LED, 0);
            ESP_LOGI(TAG, "订阅主题 '%s', 消息ID=%d", CONFIG_MQTT_TOPIC_LED, msg_id);
            break;
            
        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "MQTT已断开");
            mqtt_connected = false;
            break;
            
        case MQTT_EVENT_SUBSCRIBED:
            ESP_LOGI(TAG, "订阅确认, 消息ID=%d", event->msg_id);
            break;
            
        case MQTT_EVENT_UNSUBSCRIBED:
            ESP_LOGI(TAG, "取消订阅, 消息ID=%d", event->msg_id);
            break;
            
        case MQTT_EVENT_PUBLISHED:
            ESP_LOGD(TAG, "消息发布完成, 消息ID=%d", event->msg_id);
            break;
            
        case MQTT_EVENT_DATA:
            ESP_LOGI(TAG, "收到数据: 主题=%.*s, 数据=%.*s",
                     event->topic_len, event->topic,
                     event->data_len, event->data);
            
            // 处理LED控制消息
            if (strncmp(event->topic, CONFIG_MQTT_TOPIC_LED, event->topic_len) == 0) {
                if (event->data_len > 0) {
                    if (event->data[0] == '1' || event->data[0] == 'o' || event->data[0] == 'O') {
                        user_gpio_set_led(true);
                        ESP_LOGI(TAG, "LED已开启");
                    } else if (event->data[0] == '0' || event->data[0] == 'f' || event->data[0] == 'F') {
                        user_gpio_set_led(false);
                        ESP_LOGI(TAG, "LED已关闭");
                    } else {
                        ESP_LOGW(TAG, "未知的LED控制命令: %.*s", event->data_len, event->data);
                    }
                }
            }
            break;
            
        case MQTT_EVENT_ERROR:
            ESP_LOGE(TAG, "MQTT错误");
            mqtt_connected = false;
            break;
            
        default:
            ESP_LOGD(TAG, "MQTT事件ID: %d", event->event_id);
            break;
    }
}

/**
 * @brief 发布MQTT消息
 * 
 * @param topic 主题
 * @param data 数据
 * @return esp_err_t ESP_OK表示成功，其他表示失败
 */
esp_err_t user_mqtt_publish(const char *topic, const char *data)
{
    if (!mqtt_connected || client == NULL) {
        ESP_LOGW(TAG, "MQTT未连接，无法发布消息");
        return ESP_FAIL;
    }
    
    int msg_id = esp_mqtt_client_publish(client, topic, data, strlen(data), 0, 0);
    if (msg_id < 0) {
        ESP_LOGE(TAG, "消息发布失败");
        return ESP_FAIL;
    }
    
    ESP_LOGD(TAG, "消息已发布到主题 '%s', 消息ID=%d", topic, msg_id);
    return ESP_OK;
}

/**
 * @brief 检查MQTT连接状态
 * 
 * @return bool true表示已连接，false表示未连接
 */
bool user_mqtt_is_connected(void)
{
    return mqtt_connected;
}

/**
 * @brief 断开MQTT连接
 * 
 * 主动断开MQTT连接。
 */
void user_mqtt_disconnect(void)
{
    if (client != NULL) {
        esp_mqtt_client_stop(client);
        mqtt_connected = false;
        ESP_LOGI(TAG, "MQTT连接已断开");
    }
}